﻿using System;

namespace Silver3D.Math
{
    public struct Color4
    {
        private Vec4 v;

        public double A { get { return v.X; } set { Util.Clamp(ref value, 0.0, 1.0); v.X = value; } }
        public double R { get { return v.Y; } set { Util.Clamp(ref value, 0.0, 1.0); v.Y = value; } }
        public double G { get { return v.Z; } set { Util.Clamp(ref value, 0.0, 1.0); v.Z = value; } }
        public double B { get { return v.W; } set { Util.Clamp(ref value, 0.0, 1.0); v.W = value; } }

        public Color4(byte a, byte r, byte g, byte b)
        {
            v = new Vec4((double)a, (double)r, (double)g, (double)b) / 255.0;
        }

        public Color4(double a, double r, double g, double b)
        {
            v = new Vec4(a, r, g, b);
            v.Clamp(0.0, 1.0);
        }

        public Color4(Vec4 argb)
        {
            v = new Vec4(argb);
            v.Clamp(0.0, 1.0);
        }

        private uint GetComponent(double c, int shift)
        {
            return ((uint)(c * 255.0)) << shift;
        }

        public uint ToUInt32()
        {
            return (GetComponent(v.X, 24) | GetComponent(v.Y, 16) | GetComponent(v.Z, 8) | GetComponent(v.W, 0));
        }

        public int ToInt32()
        {
            unchecked
            {
                return (int)ToUInt32();
            }
        }

        public static Color4 operator +(Color4 a, Color4 b)
        {
            return new Color4(a.v + b.v);
        }

        public static Color4 operator -(Color4 a, Color4 b)
        {
            return new Color4(a.v - b.v);
        }

        public static Color4 operator *(Color4 a, Color4 b)
        {
            return new Color4(a.v * b.v);
        }

        public static Color4 operator /(Color4 a, Color4 b)
        {
            return new Color4(a.v / b.v);
        }

        public static bool operator ==(Color4 a, Color4 b)
        {
            return a.v == b.v;
        }

        public static bool operator !=(Color4 a, Color4 b)
        {
            return a.v != b.v;
        }

        public override bool Equals(object obj)
        {
            return (obj != null) && (obj is Color4) && ((Color4)obj) == this;
        }

        public override int GetHashCode()
        {
            return v.GetHashCode();
        }

        public override string ToString()
        {
            return string.Format("Color4({0},{1},{2},{3})", v.X, v.Y, v.Z, v.W);
        }
    }
}
